iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 25
1
Software Development

為什麼世界需要Typescript系列 第 25

什麼是柯里化 - 25

  • 分享至 

  • xImage
  •  
  • strictFunctionTypes

嚴格檢查函數類型的檢查, 例如泛型的協變和逆變檢查. 泛型類型參數分為三種情況

  • 不變量 -- 泛型參數類型不能更改
  • 協變量 -- 泛型參數類型可以從一個類別(Class) 變更為它的基本類別(Class), C# 中使用 out 關鍵字標記註明"協變量"
  • 逆變量 -- 泛型參數類型可以從一個類別(Class) 變更為它的子類別(Class), C# 中使用 in 關鍵字標記註明"逆變量"

下面程式碼示範 Food 基本類別, FishSoup 是 Food 的子類別

class Food {
   name: string = "Food";
}

class FishSoup extends Food {
   name: string = "FishSoup";
   price: number = 123;
}

然後有一個比較大小的泛型介面如下

interface Comparer<T> {
   compare: (a: T, b: T) => number;
}

有兩個變數宣告如下, foodComparer 比較食物, 而 fishSoupComparer 比較魚湯

declare let foodComparer: Comparer<Food>;
declare let fishSoupComparer: Comparer<FishSoup>;

foodComparer = fishSoupComparer;
fishSoupComparer = foodComparer;

Typescript 會告知你 fishSoupComparer 不能指定給 foodComparer

Type 'Comparer<FishSoup>' is not assignable to type 'Comparer<Food>'.
  Property 'price' is missing in type 'Food' but required in type 'FishSoup'.

因為Typescript 不允許 "函數方法變數" 進行逆變! 注意 Comparer 介面中的 compare 是 函數方法變數, 不是方法.

compare : (a: T, b: T) => number;

如果改成以下比對大小介面, 則協變和逆變都可以進行

interface Comparer<T> {
   compare(a: T, b: T): number;
}

Typescript 的超能力

先前有介紹過元組(Tuple), 我們來複習一下, 元組類型是允許你表示一個已知固定數量元素類型的數組. 我們來看一個例子

type test01 = [1, 2, 3];

我們可以宣告 type test01, 強制 test01 為一個元組(Tuple), 並且強制內容為 1, 2, 3. 如果宣告一個變數a 如下

let a: test01 = [4, 5, 6];

Typescript 會提醒你下面錯誤訊息

Type '4' is not assignable to type '1'.
Type '5' is not assignable to type '2'.
Type '6' is not assignable to type '3'.

同樣地, 我們可以宣告 type test01

type test01 = [1, string, number];

表示強制這個元組一定要是

  • 第一個位置內容一定要 1
  • 第二個位置的類型一定要是 string
  • 第三個位置的類型一定要是 number

我們來看看輸入下面程式碼會發生甚麼事?

let a: test01 = [1, 2, 3];

Typescript 會告知你第二個位置有下列錯誤訊息

Type 'number' is not assignable to type 'string'.

很厲害的元組能力吧? 為什麼我會提到這元組? 這要說到....

柯里化(Curring) -- 接受多個參數的函數變換成接受一個單一參數的函數, 並且返回接受餘下的參數而且返回結果的新函數的技術.

啥!? 聽不懂. 連我都聽得霧煞煞.

例如這有一個 add 方法如下所示

function add(a: number, b:number) : number {
   return a + b;
}

正常呼叫 add 方法是

add(1, 2)

但我們想要宣告一個函數 foo 等於 add 方法, 然後呼叫這個 foo 方式是

(foo(1))(2)

add 方法需要兩個輸入參數, 但我們透過一個技術, 把原本要兩個輸入參數的 add 方法, 變成 foo 方法, 而 foo 的方法只需要一個參數, 這就是 "柯里化".

注意, add 方法原本是回傳數字, 但經過 "柯里化" 的 foo 方法回傳的是函數.

這樣整個過程應該了解了吧?


上一篇
config - 24
下一篇
動手做柯里化 - 26
系列文
為什麼世界需要Typescript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言